package org.example.searcher;

import java.io.*;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;

/*
* 1.遍历所有目录，读取html文档，解析成文本
* 2.每一行都对应一个文档，包含标题，url，正文
* */
public class Parser {
    //JAVA API 路径
    private static final String INPUT_PATH="D:\\doc_searcher_index\\jdk-17.0.11_doc-all\\docs\\api";
    //创建index实例
    private Index index=new Index();
    //解析parseContent时间
    private AtomicLong t1=new AtomicLong(0);
    //addDoc时间
    private AtomicLong t2=new AtomicLong(0);
    public void run()  {
        long beg=System.currentTimeMillis();
        System.out.println("索引制作开始");
        //1.枚举出INPUT_PATH下的所有html文件
        ArrayList<File> fileList=new ArrayList<>();
        enumFile(INPUT_PATH,fileList);
        //2.解析文档内容
        for (File f:fileList){
            System.out.println("开始解析"+f.getAbsolutePath()+"....");
            parseHTML(f);
        }
        //3.把内存构造的索引保存到磁盘
        index.save();
        long end=System.currentTimeMillis();
        System.out.println("索引制作结束！消耗时间："+(end-beg)+"ms");
    }
    public void runByThread(){
        long beg=System.currentTimeMillis();
        System.out.println("索引开始制作");
        //1.枚举出INPUT_PATH下的所有html文件
        ArrayList<File> files=new ArrayList<>();
        enumFile(INPUT_PATH,files);
        //2.解析文档内容
        CountDownLatch latch=new CountDownLatch(files.size());
        ExecutorService executorService= Executors.newFixedThreadPool(6);
        for (File f:files){
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("解析："+f.getAbsolutePath());
                    parseHTML(f);
                    latch.countDown();
                }
            });
        }
        try {
            //await会阻塞，把所有选手都调用countDown以后才会继续执行
            latch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        //手动的把线程池里面的线程杀掉
        executorService.shutdown();
        //3.把内存构造的索引保存到磁盘
        index.save();
        long end=System.currentTimeMillis();
        System.out.println("索引制作结束！消耗时间："+(end-beg)+"ms");
        System.out.println("t1:"+t1+"t2"+t2);
    }


    private  void parseHTML(File f) {
        //1.解析HTML标题
        String title=parseTitle(f);
        //2.解析HTML的URL
        String url=parseUrl(f);
        //3.解析HTML的正文
        long beg=System.nanoTime();
        //String content=parseContent(f);
        String content=parseContentByRegex(f);
        long mid=System.nanoTime();
        //把解析出来的信息加载到索引
        index.addDoc(title,url,content);
        long end=System.nanoTime();
        t1.addAndGet(mid-beg);
        t2.addAndGet(end-mid);
    }

    public  String parseContent(File f)  {
        try (BufferedReader bufferedReader=new BufferedReader(new FileReader(f),1024*1024)){
            boolean isCopy=true;
            StringBuilder content=new StringBuilder();
            while (true){
                int ret=bufferedReader.read();
                if(ret==-1){
                    //读完了
                    break;
                }
                char c=(char) ret;
                if(isCopy){
                    if (c=='<'){
                        isCopy=false;
                        continue;
                    }
                    if (c=='\n'||c=='\r'){
                        c=' ';
                    }
                    content.append(c);
                }else {
                    if (c=='>'){
                        isCopy=true;
                    }
                }
            }
            return content.toString();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public String parseContentByRegex(File f){
        //读取文件内容放入String
        String content=readFile(f);
        //替换script
        content=content.replaceAll("<script.*?>(.*?)</script>"," ");
        //替换普通html标签
        content=content.replaceAll("<.*>"," ");
        //把多个空格合并成一个
        content=content.replaceAll("\\s+"," ");
        return content;
    }

    private String readFile(File f) {
        try(BufferedReader bufferedReader=new BufferedReader(new FileReader(f))) {
            StringBuilder content=new StringBuilder();
            while (true){
                int ret=bufferedReader.read();
                if (ret==-1){
                    break;
                }
                char c=(char) ret;
                if (c=='\n'||c=='\r'){
                    c=' ';
                }
                content.append(c);
            }
            return content.toString();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static String parseUrl(File f) {
    String part1="https://docs.oracle.com/en/java/javase/17/docs/api/";
    String part2=f.getAbsolutePath().substring(INPUT_PATH.length());
    return part1+part2;
    }

    public static String parseTitle(File f) {
        String title=f.getName();
        return title.substring(0,title.length()-".html".length());
    }

    private static void enumFile(String inputPath, ArrayList<File> fileList) {
        //1.遍历所有目录
        File root=new File(inputPath);
        //把root下的所有目录罗列处理
        File[] files=root.listFiles();
       //递归遍历所有目录
        for (File f:files){
            if(f.isDirectory()){
                enumFile(f.getAbsolutePath(),fileList);
            }else if(f.getAbsolutePath().endsWith(".html")) {
                fileList.add(f);
            }
        }
    }

    public static void main(String[] args) throws IOException {
        Parser parser=new Parser();
        parser.runByThread();
    }
}
